package application;

import gui.GUI;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Random;

import javax.swing.JOptionPane;

public class Aesp extends ArrayList<Project> {

	/**
	 * Vi måste ha den i hela procent annars blir kompilatorn sur // Alex
	 */
	private int similarityThreshold = 30;

	private Double[][] charsData;
	private String[][] inputData;
	private String[] charsNames;
	private HashMap<String, Double> minValue;
	private HashMap<String, Double> maxValue;

	public Aesp() throws IOException {
		super();
		importCharData();
	}

	public Aesp(File file) throws Exception {
		super();
		importCharData();
		readFromFile(file);
	}

	public String[] getCharsNames() {
		return charsNames;
	}

	public Double[][] getCharsData() {
		return charsData;
	}

	public String[][] getInputData() {
		return inputData;
	}

	public void importCharData() throws IOException {
		String curDir = System.getProperty("user.dir") + "/data/";
		BufferedReader reader = new BufferedReader(new FileReader(curDir
				+ "characteristicsData.txt"));
		String line = null;
		int rows = 0;
		int count = 0;
		while ((line = reader.readLine()) != null) {
			count++;
			if (!line.endsWith("=")) {
				rows++;
			}
		}
		charsData = new Double[rows][6];
		charsNames = new String[count];
		count = 0;
		int rowCount = 0;
		reader = new BufferedReader(new FileReader(curDir
				+ "characteristicsData.txt"));
		while ((line = reader.readLine()) != null) {
			String[] subStrings;
			if (!line.endsWith("=")) {
				subStrings = line.split(",");
				charsNames[count] = subStrings[0];
				count++;
				for (int i = 0; i < 6; i++) {
					if (subStrings[i + 1].equalsIgnoreCase("-")) {
						charsData[rowCount][i] = null;
					} else {
						charsData[rowCount][i] = Double
								.parseDouble(subStrings[i + 1]);
					}
				}
				rowCount++;
			} else {
				subStrings = line.split("=");
				String s = subStrings[0];
				charsNames[count] = s;
				count++;
			}
		}
	}



	public void readFromFile(File file) throws Exception {
		BufferedReader reader = new BufferedReader(new FileReader(file));
		String line = null;
		int totalRows = 0;
		while ((line = reader.readLine()) != null) {
			totalRows++;
		}
		inputData = new String[totalRows][charsNames.length];
		minValue = new HashMap<String, Double>();
		maxValue = new HashMap<String, Double>();
		reader = new BufferedReader(new FileReader(file));
		line = null;
		boolean first = true;
		int count = 0;


		while ((line = reader.readLine()) != null) {
			String[] column = null;
			column = line.substring(0, 137).trim().split(",");
			Project p = new Project();
			Double value;
			String name;
			for (int i = 0; i < charsData.length; i++) {
				inputData[count][i] = column[i];
				name = charsNames[i];
				value = charsData[i][EffortMultiplyer.
				                     getVectorPlace(column[i])];
				p.addCharacteristic(name, value);
				if (!first) {
					if (minValue.get(name) > value) {
						minValue.put(name, value);
					} else if (maxValue.get(name) < value) {
						maxValue.put(name, value);
					}
				} else {
					maxValue.put(name, value);
					minValue.put(name, value);
				}
			}
			int moreChars = charsNames.length - charsData.length;
			if (moreChars > 0) {
				for (int i = 0; i < moreChars; i++) {
					inputData[count][charsData.length + i] = column[charsData.length + i];
					name = charsNames[charsData.length + i];
					value = Double.parseDouble(column[charsData.length + i]);
					p.addCharacteristic(name, value);
					if (!first) {
						if (minValue.get(name) > value) {
							minValue.put(name, value);
						}
						if (maxValue.get(name) < value) {
							maxValue.put(name, value);
						}
					} else {
						maxValue.put(name, value);
						minValue.put(name, value);
					}
				}
				first = false;

				// Add project to aesp database
				add(p);
			}
			count++;
		}
	}



	/*
	 * Create project with characteristic relations based on:
	 * http://promise
	 * .site.uottawa.ca/SERepository/datasets/cocomonasa.arff
	 */



	public double estimateEffort(Project pro) throws Exception {
		return estimateEffort(pro, EstimationUnit.PERSON_HOURS);
	}

	/**
	 * 
	 * 
	 * @param pro
	 * @param unit
	 * @return
	 * @throws Exception 
	 */
	public double estimateEffort(Project pro, EstimationUnit unit) throws Exception {
		double effort = 0;
		pro.setDeltaValue(minValue, maxValue);
		int simularitySum = 0;
		ArrayList<Project> okProjects = new ArrayList<Project>();
		Double proLoco = pro.getCharacteristicValue("kloc");
		int similarity;
		for (Project p : this) {

			similarity = pro.compareWith(p);
			if (similarity >= similarityThreshold) {
				simularitySum = simularitySum + similarity;
				okProjects.add(p);
			}

		}
		
		if(simularitySum == 0){
			throw new Exception();
		}
		//System.out.println(okProjects.size());
		for (Project p : okProjects) {
			// Calculate similarity between new project and db entry

			similarity = pro.compareWith(p);
			
				// Use db entry to calculate weighted effort

				Double pLoco = p.getCharacteristicValue("kloc");
				Double pEffort = p.getCharacteristicValue("effort");
				Double simularityDiff = ((double)(similarity) / (double)(simularitySum));
				effort += ((proLoco/pLoco)*(pEffort)*(simularityDiff));
			
		}
		// Format according to specified input
		switch (unit) {
		case PERSON_DAYS:
			return effort;
		case PERSON_MONTHS:
			return effort/20;
		case PERSON_YEARS:
			return effort/20/11;
		default:
			return effort*8;
		}
	}

	public static void main(String[] args) {


		try {
			Aesp aesp = new Aesp();
			GUI gui = new GUI(aesp);
			gui.initGUI();
		} catch (Exception x) {
			System.err.format("IOException: %s%n", x);
		}
	}



	public void setThreshold(int threshold) {
		similarityThreshold = threshold;
	}
	public int getSizeCharsNames(){
		return (charsNames.length - 1);
	} 

	public int getThreshold () {
		return similarityThreshold;
	}
}
